<?php
/**
 * Object representing a content field
 *
 * @package Concerto
 * @subpackage Models
 * @author Jason Raede <jason@torchdm.com>
 */
namespace application\models;
use application\utilities\Utility;
class ContentField extends DBObject {

	/**
	 * The field's database ID
	 *
	 * cf_id
	 *
	 * @var int
	 */
	protected $id;
	
	/**
	 * Field is required?
	 *
	 * cf_required
	 *
	 * @var bool
	 */
	protected $required;
	
	/**
	 * Field's content type
	 *
	 * cf_content_type
	 *
	 * @var int
	 */
	protected $contentType;
	
	/**
	 * Field order in forms
	 *
	 * cf_order
	 *
	 * @var int
	 */
	protected $order;
	
	/**
	 * @deprecated
	 */
	protected $orderColumn;
	
	/**
	 * Field's data type
	 *
	 * cf_data_type
	 *
	 * @var string
	 */
	protected $dataType;
	
	/**
	 * Field's display name. This is used when calling displayField or getField
	 *
	 * cf_display_name
	 *
	 * @var string
	 */
	protected $displayName;
	
	/**
	 * Field's column name in the database. This may be the same as the actual column name, or may
	 * be the first part of the columns associated with this field
	 *
	 * cf_column
	 *
	 * @var string
	 */
	protected $column;
	
	/**
	 * Any auxiliary data associated with the field
	 *
	 * @deprecated Ditched in favor of the cn_field_meta table
	 */
	protected $aux;
	
	/**
	 * Field's default value
	 *
	 * cf_default
	 *
	 * @var mixed
	 */
	protected $default;
	
	/**
	 * The optional field description to show in forms
	 *
	 * cf_description
	 *
	 * @var string
	 */
	protected $description;
	
	/**
	 * Show the field in the manage panel?
	 *
	 * cf_show
	 *
	 * @var bool
	 */
	protected $show;
	
	/**
	 * Show on the login form?
	 *
	 * cf_show_login
	 *
	 * @var bool
	 */
	protected $showLogin;
	
	/**
	 * Show on the signup/register form?
	 *
	 * cf_show_signup
	 *
	 * @var bool
	 */
	protected $showSignup;
	
	/**
	 * Show on the edit profile form?
	 *
	 * cf_show_edit_profile
	 *
	 * @var bool
	 */
	protected $showEditProfile;
	
	
	/**
	 * Array of values associated with this field in the cn_field_meta table
	 *
	 * @var array
	 */
	protected $meta = array();
	
	/**
	 * If $id is provided, intialize the object with its database data
	 *
	 * @param int $id
	 */
	public function __construct($id = null) {
		if($id) {
			$row = DB()->getRow("SELECT * FROM `cn_content_fields` WHERE `cf_id`='$id'", 'array');
			foreach($row as $column=>$value) {
				$var = Utility::toCamelCase(str_replace('cf_', '', $column));
				$this->$var = $value;
			}
			// Get meta
			$meta = DB()->getResults("SELECT * FROM `cn_field_meta` WHERE `cfm_field`='$id'");
			foreach($meta as $var) {
				$this->meta[$var->cfm_key] = $var->cfm_value;
			}
		}
	}
	
	/**
	 * Returns the value of a meta property
	 *
	 * @param string $property
	 * @return mixed
	 */
	public function getMeta($property) {
		return $this->meta[$property];
	}
	
	/**
	 * Initialize the object with data from the parameters
	 *
	 * @param array $params Array of data corresponding to this object's properties
	 */
	public function create($params) {
		if($params['displayName'] && isset($params['contentType']) && $params['dataType']) {
			foreach($params as $key=>$value) {
				$this->$key = $value;
			}
			
			// Make the column name
			if($params['contentType'] == 'user') {
				$column = 'user_'.Utility::makeColumn($this->displayName);
			}
			else {
				$column = 'c'.$params['contentType'].'_'.Utility::makeColumn($this->displayName);
			}
			$columns = DB()->getVarArray("SELECT `cf_column` FROM `cn_content_fields` WHERE `cf_content_type`='$this->contentType'");
			$this->column = Utility::makeUnique($column, $columns);
		}
		else {
			Utility::triggerError('You must provide a display name, content type, and data type for a new data field.');
		}
	}
	
	/**
	 * Returns an array of database columns corresponding to this object's properties
	 *
	 * @return array
	 */
	public function propertiesToSql() {
		$properties = get_object_vars($this);
		unset($properties['id']);
		unset($properties['meta']);
		$sql = array();
		foreach($properties as $key=>$value) {
			$sql['cf_'.Utility::toSqlCase($key)] = $value;
		}
		return $sql;
	}
	
	/**
	 * @deprecated Merged into save()
	 */
	public function add() {
		return $this->save();	
	}
	
	/**
	 * Insert or update the object's database row(s)
	 *
	 * Note that changing the column or data type is not allowed
	 *
	 * @return array DBObject status array.
	 */
	public function save() {
		$db = $this->propertiesToSql();
		if($this->id) {
			unset($db['cf_column']);
			unset($db['cf_data_type']);
			DB()->update('cn_content_fields', 'cf_id', $this->id, $update);
		}
		else {
			DB()->insert('cn_content_fields', $db);
			$this->id = DB()->lastInsert();
		}
		
		
		// Any custom save handlers for the data type?
		$dataType = 'application\\datatypes\\'.$this->dataType;
		
		$dataType::save($this);
		
		return array('status'=>'success', 'id'=>$this->id);
	}
	
	/**
	 * Remove the field from the database, including its associated columns in the
	 * content or users table
	 *
	 * @return array DBObject status array.
	 */
	public function delete() {
		DB()->query("DELETE FROM `cn_content_fields` WHERE `cf_id`='$this->id'");
		
		// Delete fields on content table
		$dataType = 'application\\datatypes\\'.$this->dataType;
		$fields = $dataType::$fields;
		$columnsToDrop = array();
		if(count($fields)) {
			if($this->contentType) $alter = "ALTER TABLE `cn_content_type".$this->contentType."`";
			else $alter = "ALTER TABLE `cn_users`";
			foreach($fields as $field) {
				$column = ($field['column']) ? $this->column.'_'.$field['column'] : $this->column;
				$columnsToDrop[] = $column;
			}
			$dropSyntax = 'DROP COLUMN `'.implode('`, DROP COLUMN `', $columnsToDrop).'`';
			DB()->query($alter.' '. $dropSyntax);
		}
		
		// Any custom delete handlers for the data type?
		$dataType::delete();
		
		return array('status'=>'success');
	}
}

?>